// SevenSegment.cpp : implementation file
//

#include "stdafx.h"
#include "8085.h"
#include "SevenSegment.h"
#include "constants.h"
#include "MyException.h"
#include <math.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define DISPLAY_BLANK       0
#define DISPLAY_HYPHEN      32
#define DISPLAY_G           93
#define DISPLAY_H           118
#define DISPLAY_L           88
#define DISPLAY_T           120

/////////////////////////////////////////////////////////////////////////////
// CSevenSegment dialog


CSevenSegment::CSevenSegment()
{
    Init();
}


/////////////////////////////////////////////////////////////////////////////
// CSevenSegment message handlers

void CSevenSegment::Init()
{

}

void CSevenSegment::Create(int XPos,int  YPos,int nLen,int nWidth,int nAngle)
{
    m_nLEDSegmentLength=nLen<0?14:nLen;
    m_nLEDSegmentWidth=nWidth<0?8:nWidth;
    ChangePosition(XPos,YPos,nAngle);
}

void CSevenSegment::Create(CPoint p,int nLen,int nWidth,int nAngle)
{
    Create(p.x,p.y,nLen,nWidth,nAngle);
}

void CSevenSegment::ChangePosition(int XPos, int YPos,int nAngle)
{
    // create the position of the seven segment LED display
    int i=0;
    int nLength;
    //int x,y;
    const int nDist=m_nLEDSegmentWidth/2;
    CPoint p(XPos,YPos);
    
    //x = XPos;
    //y = YPos;
    //  __
    nLength = m_cSegments[i].Create(p,m_nLEDSegmentLength,m_nLEDSegmentWidth,0+nAngle);
    p = m_cSegments[i++].GetFourthPoint();
    p.x += nDist;
    p.y += nDist;
    //       __
    //         |
    //x +=nLength+nDist;
    //y +=nDist;

    nLength = m_cSegments[i].Create(p,m_nLEDSegmentLength,m_nLEDSegmentWidth,-90+nAngle);
    p = m_cSegments[i++].GetFourthPoint();    
    //      __
    //        |
    //        |
    //y +=nLength+nDist;
    p.y += nDist;
    nLength = m_cSegments[i].Create(p,m_nLEDSegmentLength,m_nLEDSegmentWidth,-90+nAngle);
    p = m_cSegments[i++].GetFourthPoint();
    //      __
    //        |
    //      __|
    p.y +=nDist;
    p.x -=nDist;
    //y +=nLength+nDist;
    //x -=nDist;
    nLength = m_cSegments[i].Create(p,m_nLEDSegmentLength,m_nLEDSegmentWidth,180+nAngle);
    p = m_cSegments[i++].GetFourthPoint();
    //      __
    //        |
    //     |__|
    p.x -= nDist;
    p.y -= nDist/2;
    nLength = m_cSegments[i].Create(p,m_nLEDSegmentLength,m_nLEDSegmentWidth,90+nAngle);
    p = m_cSegments[i++].GetFourthPoint();
    //      __
    //      __|
    //     |__|
    p.x += nDist; //XPos;
    p.y -= nDist;
    nLength = m_cSegments[i].Create(p,m_nLEDSegmentLength,m_nLEDSegmentWidth,0+nAngle);
    i++;
    //p = m_cSegments[i++].GetFourthPoint();

    //y -= nDist;
    p.x -= nDist;
    p.y -= nDist;
    nLength = m_cSegments[i].Create(p,m_nLEDSegmentLength,m_nLEDSegmentWidth,90+nAngle);

    int nRadius = m_nLEDSegmentLength/3+1;

    m_cLedDot.Create(XPos+GetWidth()+nRadius+5,YPos+GetHeight(),nRadius,nRadius);
}

void CSevenSegment::Draw(CDC *pDC, unsigned nState)
{
    // nState represents the on or off state of the 7 segments
    int i=0;
    m_cSegments[i++].Draw(pDC,nState&LED_0?m_LedOn:m_LedOff);
    m_cSegments[i++].Draw(pDC,nState&LED_1?m_LedOn:m_LedOff);
    m_cSegments[i++].Draw(pDC,nState&LED_2?m_LedOn:m_LedOff);
    m_cSegments[i++].Draw(pDC,nState&LED_3?m_LedOn:m_LedOff);
    m_cSegments[i++].Draw(pDC,nState&LED_4?m_LedOn:m_LedOff);
    m_cSegments[i++].Draw(pDC,nState&LED_5?m_LedOn:m_LedOff);
    m_cSegments[i++].Draw(pDC,nState&LED_6?m_LedOn:m_LedOff);
    m_cLedDot.Draw(pDC,nState&LED_DOT?m_LedOn:m_LedOff);
}

// get the width of a seven segment display
int CSevenSegment::GetWidth()
{
    // get the left most point, which is either the 0th segment or
    // the 3rd segment
    CPoint leftMost,rightMost;
    CPoint p1 = m_cSegments[0].GetPoint(0);
    CPoint p2 = m_cSegments[3].GetPoint(3);

    if(p1.x<p2.x)
    {
        leftMost = p1;
        rightMost = m_cSegments[3].GetPoint(3);
    }
    else
    {
        leftMost = p2;
        rightMost = m_cSegments[0].GetPoint(3);
    }
    return abs(rightMost.x - leftMost.x);
}

int CSevenSegment::GetHeight()
{
    // get the topmost point, which is either the 0th point in the 0th
    // segment or the 2nd point in the 0th segment
    CPoint topMost,bottomMost;
    CPoint p1 = m_cSegments[0].GetPoint(1);
    CPoint p2 = m_cSegments[0].GetPoint(2);

    if(p1.y<p2.y)
    {
        topMost = p1;
        bottomMost = m_cSegments[3].GetPoint(4);
    }
    else
    {
        topMost = p2;
        bottomMost = m_cSegments[3].GetPoint(5);
    }
    return abs(bottomMost.y - topMost.y);
}

// represent the number 0-9A-F etc in the seven segment
// display
int CSevenSegment::NumTo7Segment(int num)
{
    static int a[]={
		//	0  1  2	 3	 4	 5	 6 7   8  9
			95,6,59,47,102,109,125,7,127,111, 
		//    a  b  c  d	e	f
			119,124,89,62,121,113,
            DISPLAY_BLANK,
            LED_DOT,
            DISPLAY_HYPHEN,
            DISPLAY_G,

	};
	static int size_of_array = (sizeof(a)/sizeof(a[0]));
	if ( num >= size_of_array ) {
		CString msg;
		msg.Format(
			"Illegal data '%d' requested for display on LED.  Valid values are from 0 to %d",
			num,
			size_of_array - 1  );
		
		throw CMyException(severe,	illegal_led_display_request, msg );
	}

    ASSERT(num<(sizeof(a)/sizeof(a[0])));
	return a[num];
}


int CSevenSegment::NumToSegment(int num)
{
   // this is used in the implementation of the system call
   //   a = 0d
   //   c = 00 to 03
   //   This function returns the equivalent code to light up one
   //   segment

    int temp=0; // initially everything is reset 

    num =~num;
    if(num & 16) temp |=LED_0;
    if(num & 32)  temp |=  LED_1;
    if(num & 64)  temp |=  LED_2;
    if(num & 128) temp |=  LED_3;
    if(num & 2)   temp |=  LED_4;
    if(num & 1)   temp |=  LED_5;
    if(num & 4)   temp |=  LED_6;
    if(num & 8)   temp |=  LED_DOT;
    return temp;
}
